package com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem;

import com.clp.protocol.iec104.definition.Tc;
import com.clp.protocol.iec104.definition.TypeTag;
import com.clp.protocol.core.pdu.nbytepdu.BaseNBytePduClip;
import com.clp.protocol.core.pdu.ByteToStringFormat;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

import java.util.Objects;
import java.util.function.Consumer;

/**
 * 双点遥控信息元素对象
 */
@Getter
public class C_DC_NA_1_InfoElem extends TcInfoElem {

    /**
     * 命令类型
     */
    private Tc.CmdType cmdType;

    /**
     * 开关状态
     */
    private Tc.TwoPointSwitch twoPointSwitch;

    public C_DC_NA_1_InfoElem() {
        this(null, null);
    }

    public C_DC_NA_1_InfoElem(Tc.CmdType cmdType, Tc.TwoPointSwitch twoPointSwitch) {
        super(TypeTag.C_DC_NA_1);
        this.cmdType = cmdType;
        this.twoPointSwitch = twoPointSwitch;
    }

    @Override
    public C_DC_NA_1_InfoElem refreshFrom(ByteBuf buf) {
        byte[] bytes = new byte[typeTag().getInfoElemBytesLen()];
        buf.readBytes(bytes);
        byte by = bytes[0];
        this.cmdType = Tc.CmdType.gain((by & 0x80) == 0x80 ? 1 : 0);
        this.twoPointSwitch = Tc.TwoPointSwitch.gain(by & 0x03);
        return this;
    }

    @Override
    public boolean isValid() {
        if (cmdType == null) return false;
        return twoPointSwitch != null;
    }

    @Override
    public void writeBytesTo(ByteBuf buf) {
        buf.writeByte(generateByte());
    }

    private byte generateByte() {
        byte by = 0x00; // 单点遥控信息长度为1字节
        by |= cmdType.getByteMask();
        by |= twoPointSwitch.getByteMask();
        return by;
    }

    @Override
    public void writeFormattedByteStringsTo(StringBuilder sb, String frameClipBytesSeparator, String byteSeparator, ByteToStringFormat byteFormat) {
        byte by = generateByte();
        sb.append(byteFormat.format(by));
    }

    @Override
    public void writeSimpleDescriptionTo(StringBuilder sb) {
        sb.append(cmdType).append(", ").append(twoPointSwitch);
    }

    @Override
    public void writeDetailDescriptionTo(StringBuilder sb) {
        sb.append("命令类型：").append(cmdType).append(", 开关状态：").append(twoPointSwitch);
    }

    @Override
    public Tc.Type type() {
        return Tc.Type.TWO_POINT;
    }

    @Override
    public boolean isSwitchOn() {
        return twoPointSwitch == Tc.TwoPointSwitch.ON;
    }

    @Override
    protected void forEachOneLevelChild(Consumer<BaseNBytePduClip<?>> consumer) {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        C_DC_NA_1_InfoElem that = (C_DC_NA_1_InfoElem) o;
        return cmdType == that.cmdType && twoPointSwitch == that.twoPointSwitch;
    }

    @Override
    public int hashCode() {
        return Objects.hash(cmdType, twoPointSwitch);
    }
}
